package org.payeco.risk.core;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.jeasy.rules.api.Facts;
import org.jeasy.rules.api.Rule;
import org.jeasy.rules.api.RuleListener;
import org.jeasy.rules.api.Rules;
import org.jeasy.rules.api.RulesEngine;
import org.jeasy.rules.api.RulesEngineListener;
import org.jeasy.rules.core.DefaultRulesEngine;
import org.jeasy.rules.core.RulesEngineParameters;
import org.payeco.risk.common.PayecoRiskConstant;
import org.payeco.risk.model.UserDefinedClasses;
import org.payeco.risk.model.UserDefinedParams;
import org.payeco.risk.model.UserDefinedReturnClass;
import org.payeco.risk.api.PayeocRiskRuleEngine;
import org.payeco.risk.entity.PayecoRiskRule;
import org.payeco.risk.entity.PayecoRuleMode;
import org.payeco.risk.entity.PayecoRuleModular;
import org.payeco.risk.rules.PayecoRiskComRule;
import org.payeco.risk.model.FunctionResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;


@Service
public class PayeocRiskRuleEngineImpl implements RulesEngine,PayeocRiskRuleEngine<FunctionResult> {

    private static final Logger LOGGER = LoggerFactory.getLogger(PayeocRiskRuleEngineImpl.class);

    private RulesEngineParameters parameters;
    private List<RuleListener> ruleListeners;
    private List<RulesEngineListener> rulesEngineListeners;
    private DefaultRulesEngine delegate;
    
//    @Before("execution(public * org.payeco.risk.core.service.impl.execute)")
    public void doBefore(){
    	  this.parameters = new RulesEngineParameters();
          delegate = new DefaultRulesEngine(parameters);
          ruleListeners = new ArrayList<>();
          rulesEngineListeners = new ArrayList<>();
          delegate.registerRuleListeners(ruleListeners);
          delegate.registerRulesEngineListeners(rulesEngineListeners);
          LOGGER.info(parameters.toString());
    }
	@Override
	public UserDefinedReturnClass<FunctionResult> executeOldRules(
			List<PayecoRiskRule> rules, UserDefinedClasses classList,
			UserDefinedParams params) {
		doBefore();
		UserDefinedReturnClass<FunctionResult> returnClass = new UserDefinedReturnClass<>();
		beforeExecuteRules(returnClass, classList, params);
        Rules riskrules = new Rules();
		for(PayecoRiskRule rule : rules){
			PayecoRiskComRule comRule = new PayecoRiskComRule(rule);
			riskrules.register(comRule);
		}
		Facts facts = new Facts();
		facts.put(PayecoRiskConstant.USERDEFINEDPARAMS.getValue(), params);
		facts.put(PayecoRiskConstant.USERDEFINEDCLASSES.getValue(), classList);
		facts.put(PayecoRiskConstant.USERDEFINEDRETURNCLASS.getValue(), returnClass);
	
		this.fire(riskrules, facts);
		
		afterExecuteRules(returnClass, classList, params);
		return returnClass;
	}



	private void beforeExecuteRules(
			UserDefinedReturnClass<FunctionResult> returnClass,
			UserDefinedClasses classList, UserDefinedParams params) {
		// TODO Auto-generated method stub
		LOGGER.info("beforeExecuteRules");
	}
	
	private void afterExecuteRules(
			UserDefinedReturnClass<FunctionResult> returnClass,
			UserDefinedClasses classList, UserDefinedParams params) {
		// TODO Auto-generated method stub
		LOGGER.info("afterExecuteRules");
	}

	@Override
	public UserDefinedReturnClass<FunctionResult> executeNewRules(
			List<PayecoRiskRule> rules, List<PayecoRuleModular> modulars,
			List<PayecoRuleMode> modes, UserDefinedClasses classList,
			UserDefinedParams params) {
		doBefore();
		return null;
	}

	@Override
	public RulesEngineParameters getParameters() {
		// TODO Auto-generated method stub
		return delegate.getParameters();
	}

	@Override
	public List<RuleListener> getRuleListeners() {
		// TODO Auto-generated method stub
		return delegate.getRuleListeners();
	}

	@Override
	public List<RulesEngineListener> getRulesEngineListeners() {
		// TODO Auto-generated method stub
		return delegate.getRulesEngineListeners();
	}

	@Override
	public void fire(Rules rules, Facts facts) {
		// TODO Auto-generated method stub
		delegate.fire(rules, facts);
	}

	@Override
	public Map<Rule, Boolean> check(Rules rules, Facts facts) {
		// TODO Auto-generated method stub
		return delegate.check(rules, facts);
	}

	
}
